# ruby_fetion/sipc.rb
# -*- encoding: utf-8 -*-
# License: GPL v2
# Author:  jhsea3do@gmail.com
# Version: 0.1

class SIPC

  CRLF  = "\r\n"
  CRLF2 = "\r\n\r\n"

  attr_reader :socket, :logger, :queue

  def initialize(options = {})
    uri = URI.parse options[:uri] || 'sipc://221.176.31.33:8080'
    @socket = TCPSocket.new uri.host, uri.port
    @logger = options[:logger] || Logger.new(STDOUT)
    @queue  = []
  end

  def request(sip_req)
    @logger.debug "sipc.send:\n#{sip_req}"
    self.send sip_req
    sip_res = self.recv
    @logger.debug "sipc.recv:\n#{sip_res}"
    sip_res
  end

  def request_nonblock(sip_req, sip_res = {})
    timeout = 0
    @logger.debug sip_req
    @socket.write_nonblock(sip_req)
    IO.select [@socket, nil, nil, timeout]
    res = ""
    begin 
      while chunk = @socket.read_nonblock(4096)
        res = "#{res}#{chunk}"
      end
    rescue
      @logger.error "! sipc request error: #{$!.inspect}"
    end
    @logger.debug res
    res
  end

    def send msg
      begin
        @socket.write msg
        @socket.flush
      rescue
        @logger.error "! sipc request error: #{$!.inspect}"
        # @socket.close
      end
    end

    def recv timeout = 2
      datas = []
      chunk_size = 1024
      begin
        chunk = @socket.recv(chunk_size)
        if !chunk.nil? && chunk.match(/^(M|BN)\ \d+\ SIP.*/)
          # TODO
          # if notify message to long ....
          d = chunk
          match = d.scan(/L: (\d+)/)
          if !match.nil?
            len = match[0][0].to_i
            pos = d.index(CRLF2)
            str = d[0, pos + len + 4]
            @logger.debug str
            @queue << str
            chunk = d[pos + len + 4, d.size - (pos + len + 4)]
          end
        end
        datas << chunk
        if CRLF2 == chunk[chunk.size - 4, 4]
          # nothing
        else
          match = chunk.scan(/L: (\d+)/)
          head_len = 0
          body_len = 0
          if !match.nil?
            body_len = (match[0][0]).to_i
            len_expr = "L: #{body_len}"
            expr_len = len_expr.size
            head_len = chunk.index(len_expr) + expr_len + 4
          end
          if chunk.size != (head_len + body_len)
            left_len = body_len + head_len - chunk.size
            # timeout = 2
            chunk = ''
            while true
              recv_size = [chunk_size, left_len].max
              chunk = @socket.recv(recv_size)
              break if chunk.nil?
              datas << chunk
              n = chunk.size
              break if n >= left_len
              left_len = left_len - n
            end
          end
        end
      rescue
        @logger.error "! sipc request error: #{$!.inspect}"
        # @socket.close
      end
      datas.join('')
    end
end
